﻿using System;
using System.Device.Location;
using System.Threading;
using Com.PhilChuang.Mobile.Apps.LocationSender.Utils;
using GeoCoordinate = Com.PhilChuang.Mobile.Apps.LocationSender.Model.Data.GeoCoordinate;

namespace Com.PhilChuang.Mobile.Apps.LocationSender.Model.Services.Impl
{
	public class GeoCoordinateProviderImpl : IGeoCoordinateProvider
	{
		#region Events
		public event Action<GeoCoordinate> GeoCoordinateUpdated = delegate { };
		public event Action CouldNotStart = delegate { }; 
		#endregion

		#region Instance variables
		private GeoCoordinateWatcher m_GeoCoordinateWatcher;
		#endregion

		#region Properties
		public GeoCoordinate Current { get; private set; }
		public GeoPositionStatus Status { get; private set; }
		#endregion

		#region Constructors / Dispose
		public GeoCoordinateProviderImpl ()
		{
			m_GeoCoordinateWatcher = new GeoCoordinateWatcher (GeoPositionAccuracy.High);
			m_GeoCoordinateWatcher.PositionChanged += m_GeoCoordinateWatcher_PositionChanged;
			m_GeoCoordinateWatcher.StatusChanged += m_GeoCoordinateWatcher_StatusChanged;
		}

		public void Dispose ()
		{
			Stop ();
			m_GeoCoordinateWatcher.PositionChanged -= m_GeoCoordinateWatcher_PositionChanged;
			m_GeoCoordinateWatcher.StatusChanged -= m_GeoCoordinateWatcher_StatusChanged;
			m_GeoCoordinateWatcher.Dispose ();
		}
		#endregion

		#region Functionality
		public void StartAsync ()
		{
			// THIS CODE IS UNNECESSARY NOW THAT EMULATOR SUPPORTS LOCATION SIMULATION
			// if debugging in the emulator, then display some test data
			//if (App.DeviceName == "XDeviceEmulator")
			//{
			//    ThreadPool.QueueUserWorkItem (
			//        obj => {
			//            Thread.Sleep (2000);
			//            m_GeoCoordinateWatcher_PositionChanged (
			//                this,
			//                new GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate> (
			//                    new GeoPosition<System.Device.Location.GeoCoordinate>
			//                        {
			//                            Location = new System.Device.Location.GeoCoordinate
			//                                        {
			//                                            Altitude = 0.0d,
			//                                            Latitude = 28.37578d,
			//                                            Longitude = -81.549409d,
			//                                        },
			//                            Timestamp = DateTime.UtcNow,
			//                        }));
			//        });
			//    return;
			//}

			ThreadPool.QueueUserWorkItem (
				obj => {
					try
					{
						if (!m_GeoCoordinateWatcher.TryStart (false, TimeSpan.FromSeconds (5)))
						{
							CouldNotStart ();
						}
					}
					catch (ThreadAbortException)
					{
						// swallow these
					}
				});
		}

		public void Stop ()
		{
			if (m_GeoCoordinateWatcher.Status != GeoPositionStatus.Disabled)
				m_GeoCoordinateWatcher.Stop ();
		}
		#endregion

		#region Event handlers
		private void m_GeoCoordinateWatcher_PositionChanged (object sender, GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate> e)
		{
			Current = e.Position.ToAppGeoCoordinate ();
			GeoCoordinateUpdated (Current);
		}

		private void m_GeoCoordinateWatcher_StatusChanged (object sender, GeoPositionStatusChangedEventArgs e)
		{
			Status = e.Status;
		}
		#endregion
	}
}
